﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Windows.Media.Animation;
using System.Windows;

namespace WpfAppQuestion01.Base;

public class CustomEventExtension
{

    public static EventCommandInfo GetEventTarget(DependencyObject obj)
    {
        return (EventCommandInfo)obj.GetValue(EventTargetProperty);
    }

    public static void SetEventTarget(DependencyObject obj, EventCommandInfo value)
    {
        obj.SetValue(EventTargetProperty, value);
    }

    public static readonly DependencyProperty EventTargetProperty =
        DependencyProperty.RegisterAttached("EventTarget", typeof(EventCommandInfo), typeof(CustomEventExtension), new PropertyMetadata(null, new PropertyChangedCallback(EventTargetChangeEvent)));


    private static void EventTargetChangeEvent(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        //获取附加属性绑定的命令函数和事件名称
        EventCommandInfo eventCommandInfo = (EventCommandInfo)e.NewValue;
        if (string.IsNullOrEmpty(eventCommandInfo.EventName))
            return;
        //通过反射回去事件名称
        EventInfo? eventInfo = d.GetType().GetEvent(eventCommandInfo.EventName);
        //定义一个执行方法，通过创建委托执行事件信息
        MethodInfo? methodInfo = typeof(CustomEventExtension).GetMethod("EventExecute", BindingFlags.NonPublic | BindingFlags.Static);
        if (eventInfo == null || methodInfo == null)
            return;
        var handler = Delegate.CreateDelegate(eventInfo.EventHandlerType!, methodInfo);
        //对对象添加事件执行程序
        eventInfo.AddEventHandler(d, handler);
    }

    private static void EventExecute(object sender, EventArgs e)
    {
        EventCommandInfo eventCommand = GetEventTarget((DependencyObject)sender);
        eventCommand.Command?.Execute(null);
    }
}

public class EventCommandInfo : Animatable
{
    protected override Freezable CreateInstanceCore()
    {
        return (Freezable)Activator.CreateInstance(GetType())!;
    }

    public string? EventName { get; set; }


    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    public static readonly DependencyProperty CommandProperty =
        DependencyProperty.Register("Command", typeof(ICommand), typeof(EventCommandInfo), new PropertyMetadata(null));




    public Object CommandParam
    {
        get { return (Object)GetValue(CommandParamProperty); }
        set { SetValue(CommandParamProperty, value); }
    }

    // Using a DependencyProperty as the backing store for CommandParam.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty CommandParamProperty =
        DependencyProperty.Register("CommandParam", typeof(Object), typeof(EventCommandInfo), new PropertyMetadata(null));




}
